package cc.rengu.igas.opms.core.service.trans.apppay;

import cc.rengu.igas.opms.common.dao.BankSupportCfgMapper;
import cc.rengu.igas.opms.common.dao.impl.BankSupportCfgMapperImpl;
import cc.rengu.igas.opms.common.entity.BankSupportCfgInfo;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.core.service.base.ManageService;
import cc.rengu.igas.opms.facade.bean.BindCardInfo;
import cc.rengu.igas.opms.facade.bean.EbankBindCardInfo;
import cc.rengu.igas.opms.facade.request.EbankSignAcctListQueryRequest;
import cc.rengu.igas.opms.facade.response.EbankSignAcctListQueryResponse;
import cc.rengu.igas.opms.facade.response.SignAcctInfoListQueryResponse;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.BankCodeInfo;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.BompService;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.BompServiceImpl;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.SignAcctInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.SignAcctInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.SignAcctInfo;
import cc.rengu.oltp.service.common.enums.CheckResultEnum;
import cc.rengu.oltp.service.common.enums.LimitTypeEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.model.TransLimitInfo;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.GlobalTransUtil;
import cc.rengu.oltp.utility.util.StringUtil;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 电子银行跳转收银台后绑卡列表查询
 * Created by wangcheng on 2021/8/25.
 */
public class EbankSignAcctListQueryService extends ManageService implements TransCustomImpl {
    @Override
    protected Object bizBeforeCust() throws Exception {
        EbankSignAcctListQueryRequest ebankSignAcctListQueryRequest = new EbankSignAcctListQueryRequest();
        ConvertUtil.convertOutput(ebankSignAcctListQueryRequest);
        return ebankSignAcctListQueryRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        EbankSignAcctListQueryRequest ebankSignAcctListQueryRequest = (EbankSignAcctListQueryRequest) request;
        String instId = ebankSignAcctListQueryRequest.getHeader().getInstId();
        String sessionId = ebankSignAcctListQueryRequest.getHeader().getSession();
        String userId = ebankSignAcctListQueryRequest.getUserId();

        //获取用户信息
        UserService userService = new UserServiceImpl();
        UserInfo userInfo = userService.getUserInfo(instId, userId, sessionId);
        if (null == userInfo) {
            rglog.error("用户<{}>未登录或者用户会话已过期!", userId);
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }
        String signInst = userService.getUserSignInst();

        //获取用户收银台绑卡列表
        List<BindCardInfo> bindCardInfoList = null;
        SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
        List<SignAcctInfo> signAcctInfoList = signAcctInfoMapper.selectSignAcctInfoBySignTyUserId(instId, userId, signInst);
        //判断绑卡列表信息是否为空
        if (null != signAcctInfoList && !signAcctInfoList.isEmpty()) {
            signAcctInfoList = signAcctInfoList.stream().filter(item -> AppParamConstant.YES.equals(item.getSignStatus()))
                    .sorted(Comparator.comparing(SignAcctInfo::getPayIndex)).collect(Collectors.toList());
            if (!signAcctInfoList.isEmpty()) {
                rglog.info("用户存在签约信息,userId:<{}>,signInst:<{}>", userId, signInst);
                //获取用户限额配置信息
                TransLimitInfo transLimitInfo = userService.getUserLimitCfgInfo(instId, userId, userInfo.getUserInst(), LimitTypeEnum.CASHIER.getLimitType());
                if (null == transLimitInfo) {
                    rglog.debug("用户限额未配置获取机构的默认限额信息..");
                    transLimitInfo = userService.getUserLimitCfgInfo(instId, AppParamConstant.DEFAULT_INSTID, AppParamConstant.DEFAULT_INSTID, LimitTypeEnum.CASHIER.getLimitType());
                    if (null == transLimitInfo) {
                        rglog.error("机构:<{}>未配置默认限额信息", instId);
                        throw new BizException(RespCodeEnum.ORG_LIMIT_CFG_NOT_FOUND.getRespCode(), RespCodeEnum.ORG_LIMIT_CFG_NOT_FOUND.getRespDesc());
                    }
                }
                //转换应答实体
                bindCardInfoList = convertBindCardInfo(signAcctInfoList, transLimitInfo);
            }
        }

        //调用通道接口
        if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
            rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = channelCallSceneDiscern(ebankSignAcctListQueryRequest, channelCallCfgList);
        Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
        ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
        channelBaseService.callService(txnInfo, null, channelCallCfg.getBizScene(), request);

        //获取电子银行的绑卡列表
        List<EbankBindCardInfo> ebankBindCardInfoList = (List<EbankBindCardInfo>) GlobalTransUtil.getCacheValue(TransCacheConstant.BIND_CARD_INFO_LIST);
        if (null != bindCardInfoList && null != ebankBindCardInfoList && !ebankBindCardInfoList.isEmpty()) {
            List<BindCardInfo> finalBindCardInfoList = bindCardInfoList;
            ebankBindCardInfoList = ebankBindCardInfoList.stream().filter(item -> (finalBindCardInfoList.stream().noneMatch(match -> match.getSignAcctNo().equals(item.getAcctNo())))).collect(Collectors.toList());
        }

        //组装应答报文
        EbankSignAcctListQueryResponse ebankSignAcctListQueryResponse = new EbankSignAcctListQueryResponse();
        ebankSignAcctListQueryResponse.setHeader(ebankSignAcctListQueryRequest.getHeader());
        ebankSignAcctListQueryResponse.setBindCardList(bindCardInfoList);
        ebankSignAcctListQueryResponse.setEbankBindCardInfoList(ebankBindCardInfoList);
        //根据支付密码是否为空赋值支付密码标志字段（passwordFlag）
        rglog.debug("用户密码字段是否为空:userTransPassword:<{}>", userInfo.getTransPassword());
        if (StringUtil.isEmptyOrNull(userInfo.getTransPassword())) {
            ebankSignAcctListQueryResponse.setPasswordFlag(AppParamConstant.NO);
        } else {
            ebankSignAcctListQueryResponse.setPasswordFlag(AppParamConstant.YES);
        }
        BizResponse<EbankSignAcctListQueryResponse> bizResponse = new BizResponse();
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        bizResponse.setResult(ebankSignAcctListQueryResponse);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        SignAcctInfoListQueryResponse signAcctInfoListQueryResponse = (SignAcctInfoListQueryResponse) bizResponse.getResult();
        ConvertUtil.convertInput(signAcctInfoListQueryResponse);
    }

    /**
     * 查询的数据库实体类转换为结果响应类
     * Created by liujinan on 2020/4/16.
     */
    private ArrayList<BindCardInfo> convertBindCardInfo(List<SignAcctInfo> signAcctInfos, TransLimitInfo transLimitInfo) throws Exception {
        //初始化用户单笔限额和单日限额数据
        String singleLimitAmt = transLimitInfo.getSingleLimitMaxAmt();
        String dateLimitAmt = transLimitInfo.getDayLimitAmt();
        ArrayList<BindCardInfo> bindCardInfos = new ArrayList<>();
        BompService bompService = new BompServiceImpl();
        BankSupportCfgMapper bankSupportCfgMapper = new BankSupportCfgMapperImpl();
        for (SignAcctInfo signAcctInfo : signAcctInfos) {
            //查找支持银行列表配置表获取银行名称-银行名称即银行的简称,获取银行logo的url
            String bankLogo = "";
            String bankName = signAcctInfo.getSignBankName();
            BankCodeInfo bankCodeInfo = bompService.getBankCodeInfoByBandBranchCode(signAcctInfo.getSignBankNo());
            if (null != bankCodeInfo) {
                List<BankSupportCfgInfo> bankSupportCfgInfos = bankSupportCfgMapper.selectOpmsBankSupportCfgByInstIdBankNo(signAcctInfo.getInstId(), bankCodeInfo.getCupsInstId());
                if (null != bankSupportCfgInfos && bankSupportCfgInfos.size() != 0) {
                    bankName = bankSupportCfgInfos.get(0).getBankName();
                    bankLogo = bankSupportCfgInfos.get(0).getBankLogoUrl();
                }
            }
            BindCardInfo bindCardInfo = new BindCardInfo();
            //签约协议号
            bindCardInfo.setSignToken(signAcctInfo.getSignToken());
            //签约类型
            bindCardInfo.setSignType(signAcctInfo.getSignTokenType());
            //签约账户类型
            bindCardInfo.setSignAcctType(signAcctInfo.getSignAcctType());
            //签约银行账号
            bindCardInfo.setSignAcctNo(signAcctInfo.getSignAcctNo());
            //证件类型
            bindCardInfo.setCertType(signAcctInfo.getCertType());
            //证件号码
            bindCardInfo.setCertNo(signAcctInfo.getCertNo());
            //持卡人姓名
            bindCardInfo.setCardHoldName(signAcctInfo.getCardHoldName());
            //预留手机号
            bindCardInfo.setPhoneNo(signAcctInfo.getReserveMobileNo());
            //签约发卡行行号
            bindCardInfo.setSignBankNo(signAcctInfo.getSignBankNo());
            //签约发卡行名称
            bindCardInfo.setSignBankName(bankName);
            //扣款顺序号
            bindCardInfo.setPayIndex(String.valueOf(signAcctInfo.getPayIndex()));
            //单笔限额
            bindCardInfo.setSingleLimitAmt(singleLimitAmt);
            //当日累计限额
            bindCardInfo.setDayLimitAmt(dateLimitAmt);
            //银行logo路径
            bindCardInfo.setBankLogoUrl(bankLogo);
            //小额免密限额
            bindCardInfo.setNoPasswordAmt(signAcctInfo.getNoPasswordAmt());
            //认证限额
            bindCardInfo.setAuthLimitAmt(signAcctInfo.getAuthLimitAmt());
            bindCardInfos.add(bindCardInfo);
        }
        return bindCardInfos;
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        Optional<ChannelCallCfg> channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getCallIndex().equals(ShareParamConstant.CALL_CFG_DEFAULT_BIZ_SCENE)).findFirst();
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        if (TransStatusEnum.TRANS_SUCC.equals(transStatusEnum) && null != channelResponse) {
            //TODO获取调用电子银行查询到的客户绑卡列表
            List<EbankBindCardInfo> ebankBindCardInfoList = new ArrayList<>();
            GlobalTransUtil.setCacheValue(TransCacheConstant.BIND_CARD_INFO_LIST, ebankBindCardInfoList);
        }
        return transStatusEnum;
    }
}
